package com.jingdianjichi.auth.domain.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.google.gson.Gson;
import com.jingdianjichi.auth.common.enums.AuthUserStatusEnum;
import com.jingdianjichi.auth.common.enums.IsDeletedFlagEnum;
import com.jingdianjichi.auth.domain.constants.AuthConstant;
import com.jingdianjichi.auth.domain.convert.AuthUserBOConverter;
import com.jingdianjichi.auth.domain.entity.AuthUserBO;
import com.jingdianjichi.auth.domain.redis.RedisUtil;
import com.jingdianjichi.auth.domain.service.AuthUserDomainService;
import com.jingdianjichi.auth.infra.basic.entity.*;
import com.jingdianjichi.auth.infra.basic.service.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class AuthUserDomainServiceImpl implements AuthUserDomainService {
    @Resource
    private AuthUserService authUserService;
    @Resource
    private AuthUserRoleService authUserRoleService;
    @Resource
    private AuthRoleService authRoleService;
    @Resource
    private AuthPermissionService authPermissionService;
    @Resource
    private AuthRolePermissionService authRolePermissionService;
    @Resource
    private RedisUtil redisUtil;
    private String authPermissionPrefix="auth.permission";
    private String authRolePrefix="auth.role";
    private String salt="chicken";

    private static final String LOGIN_PREFIX="loginCode";


    @Override
    @SneakyThrows
    @Transactional(rollbackFor= Exception.class)//自动回滚事务
    public Boolean register(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserBOConverter.INSTANCE
                .convertBOToEntity(authUserBO);

        /**
         * 摘要加密+加盐
         *
         */
        if(StringUtils.isBlank(authUserBO.getPassword())){
            authUser.setPassword(SaSecureUtil.md5BySalt(authUser.getPassword(),salt));
        }
        /**
         * 对称加密
         * String key="12312312";
         * authUser.setPassword(SaSecureUtil.aesEncrypt(key,authUser.getPassword()));
         */

        /**
         * 非对称加密
         * HashMap<String,String> keyMap=SaSecureUtil.rsaGenerateKeyPair();
         * String publicKey=keyMap.get("public");
         * String privateKey=keyMap.get("private");
         * authUser.setPassword(SaSecureUtil.rsaEncryptByPublic(publicKey,authUser.getPassword()));
         * System.out.println(SaSecureUtil.rsaDecryptByPrivate(privateKey,authUser.getPassword()));
         */
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        authUser.setStatus(AuthUserStatusEnum.OPEN.getCode());
        int count=authUserService.insert(authUser);
        //建立一个初步的用户角色的关联
        AuthRole authRole=new AuthRole();
        authRole.setRoleKey(AuthConstant.NORMAL_USER);
        AuthRole roleResult=authRoleService.queryByCondition(authRole);
        Long roleId=roleResult.getId();
        Long userId=authUser.getId();
        AuthUserRole authUserRole=new AuthUserRole();
        authUserRole.setUserId(userId);
        authUserRole.setRoleId(roleId);
        authUserRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        authUserRoleService.insert(authUserRole);
        //要把当前用户的角色和权限都刷到redis中
        String roleKey = redisUtil.buildKey(authRolePrefix, authUser.getUserName());
        List<AuthRole> roleList=new LinkedList<>();
        roleList.add(authRole);
        log.info("AuthUserDomainServiceImpl.register.roleList:{}",roleList);
        redisUtil.set(roleKey,new Gson().toJson(roleList));
        AuthRolePermission authRolePermission=new AuthRolePermission();
        authRolePermission.setRoleId(roleId);
        List<AuthRolePermission> authRolePermissionList = authRolePermissionService.queryByCondition(authRolePermission);
        List<Long> permissionIdList = authRolePermissionList.stream().map(AuthRolePermission::getPermissionId).collect(Collectors.toList());
        //根据permissionId查询permissionKey
        List<AuthPermission> authPermissionList=authPermissionService.queryByPermissionIdList(permissionIdList);
        String permissionKey=redisUtil.buildKey(authPermissionPrefix,authUser.getUserName());
        redisUtil.set(permissionKey,new Gson().toJson(authPermissionList));
        return count>0;
    }

    @Override
    public Boolean update(AuthUserBO authUserBO) {
        AuthUser authUser=AuthUserBOConverter.INSTANCE
                .convertBOToEntity(authUserBO);
       Integer count=authUserService.update(authUser);
       //任何更新都得与缓存进行同步的修改
        return count>0;
    }

    @Override
    public Boolean delete(AuthUserBO authUserBO) {
        AuthUser authUser=new AuthUser();
        authUser.setId(authUserBO.getId());
        authUser.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        int count=authUserService.update(authUser);
        return count>0;
    }

    @Override
    public SaTokenInfo dologin(String validCode) {
        String loginKey = redisUtil.buildKey(LOGIN_PREFIX, validCode);
        String openId = redisUtil.get(loginKey);
        if (StringUtils.isBlank(openId)) {

            return null;
        }
        AuthUserBO authUserBO=new AuthUserBO();
        authUserBO.setUserName(openId);
        this.register(authUserBO);
        StpUtil.login(openId);
        SaTokenInfo tokenInfo=StpUtil.getTokenInfo();
        return tokenInfo;
    }
}
